home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / CLASSSRC.PAK / FILENAME.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  20KB  |  862 lines

  1. //----------------------------------------------------------------------------
  2. // Borland Class Library
  3. // Copyright (c) 1995, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   5.21  $
  6. //
  7. // TFileName class implementation.
  8. //----------------------------------------------------------------------------
  9. #include <classlib/pch.h>
  10. #include <classlib/filename.h>
  11. #include <services/memory.h>
  12. #include <winsys/system.h>
  13. #include <tchar.h>
  14. #if !defined(BI_PLAT_WIN32)
  15. # include <dir.h>
  16. #endif
  17. #if defined(BI_PLAT_WIN16)
  18. # include <commdlg.h>
  19. # include <stdio.h>
  20. #endif
  21.  
  22. #define WIN95_LONGFILENAME_MAX 260
  23.  
  24. #if defined(BI_PLAT_MSW)
  25.   static _TCHAR serverNamePrefix[] = "\\\\";
  26.   static int  serverNamePrefixLen = _tcslen(serverNamePrefix);
  27. //  static _TCHAR devTerminator[] = "\\/:";
  28.   static _TCHAR ldevTerminator = ':';
  29.   static _TCHAR dirSeparator[] = "\\/";
  30.   static _TCHAR dirSeparatorCh = '\\';
  31.   static _TCHAR extSeparator = '.';
  32. #endif
  33.  
  34. //
  35. // Some Win32 APIs that are available under Win16 via DOS calls
  36. //
  37. #if defined(BI_PLAT_WIN16)
  38. DWORD
  39. GetFullPathName(LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer,
  40.                 LPSTR* lpFilePart)
  41. {
  42.   // use new MS-DOS long filename function x7160,0 - GetFullPathName
  43.   _TCHAR destPath[WIN95_LONGFILENAME_MAX]; // defined at top of file
  44.   _TCHAR const far* farFileName = lpFileName;
  45.   _TCHAR far* farDestPath = destPath;
  46.   _asm {
  47.     mov ax, 0x7160
  48.     mov cl, 0                    // GetFullPathName
  49.     mov ch, 0                    // return string contains path not SUBST drive
  50.     lds si, farFileName
  51.     les di, farDestPath
  52.     int 21h
  53.     jc  error
  54.   }
  55.  
  56.   _tcsncpy(lpBuffer, destPath, (int)(nBufferLength - 1));
  57.   goto exit;
  58. error:
  59.     _tcsncpy(lpBuffer, lpFileName, (int)(nBufferLength - 1)); // just copy in to out
  60. exit:
  61.   int bufferLen = _tcslen(lpBuffer);
  62.   // find the beginning of the filename part, lpFilePart must point to it
  63.   if (lpFilePart) {
  64.     *lpFilePart = lpBuffer;
  65.     int i;
  66.     for (i = bufferLen -1; i >= 0; i--)
  67.       if (lpBuffer[i] == '\\' || lpBuffer[i] == '/' || lpBuffer[i] == ':') {
  68.         *lpFilePart = lpBuffer + i + 1;
  69.         break;
  70.       }
  71.   }
  72.   return bufferLen;
  73. }
  74.  
  75. DWORD
  76. GetShortPathName(LPCSTR lpszLongPath, LPSTR lpszShortPath, DWORD cchBuffer)
  77. {
  78.   // use new MS-DOS long filename function x7160,1 - GetShortPathName
  79.   _TCHAR destPath[WIN95_LONGFILENAME_MAX]; // defined at top of file
  80.   _TCHAR const far* farLongPath = lpszLongPath;
  81.   _TCHAR far* farDestPath = destPath;
  82.   _asm {
  83.     mov ax, 0x7160
  84.     mov cl, 1                    // GetShortPathName
  85.     mov ch, 0                    // return string contains path not SUBST drive
  86.     lds si, farLongPath
  87.     les di, farDestPath
  88.     int 21h
  89.     jc  error
  90.   }
  91.   _tcsncpy(lpszShortPath, destPath, (int)(cchBuffer - 1));
  92.   goto exit;
  93. error:
  94.     _tcsncpy(lpszShortPath, lpszLongPath, (int)(cchBuffer - 1)); // just copy in to out
  95. exit:
  96.   return _tcslen(lpszShortPath);
  97. }
  98. #endif
  99.  
  100. //
  101. // overloaded functions to perform string scanning
  102. //
  103. static const _TCHAR far* strend(const _TCHAR far* str)
  104. {
  105.   while (*str)
  106.     str++;
  107.   return str;
  108. }
  109.  
  110. static const _TCHAR far* find(const _TCHAR far* start, const _TCHAR far* end, int match)
  111. {
  112.   while (*start != match && start != end)
  113.     start++;
  114.   return start;
  115. }
  116.  
  117. static const _TCHAR far* find(const _TCHAR far* start, const _TCHAR far* end, const _TCHAR far* set)
  118. {
  119.   const _TCHAR far* setend = set + _tcslen(set);
  120.   while (find(set, setend, *start) == setend && start != end)
  121.     start++;
  122.   return start;
  123. }
  124.  
  125. static const _TCHAR far* findl(const _TCHAR far* start, const _TCHAR far* end, int match)
  126. {
  127.   while (*start != match && start != end)
  128.     start--;
  129.   return start;
  130. }
  131.  
  132. static const _TCHAR far* findl(const _TCHAR far* start, const _TCHAR far* end, const _TCHAR far* set)
  133. {
  134.   const _TCHAR far* setend = set + _tcslen(set);
  135.   while (find(set, setend, *start) == setend && start != end)
  136.     start--;
  137.   return start;
  138. }
  139.  
  140. static const _TCHAR far* skipstr(const _TCHAR far* start, const _TCHAR far* end,
  141.                                const _TCHAR far* skip)
  142. {
  143.   while (*skip && *start == *skip && start != end)
  144.     start++, skip++;
  145.  
  146.   return start;
  147. }
  148.  
  149. //-----
  150. // Low level helper functions for parsing filename parts
  151. //
  152.  
  153. //
  154. //
  155. //
  156. static string formServer(const _TCHAR far* serverName)
  157. {
  158.   if (!serverName)
  159.     return serverName;
  160.  
  161.   const _TCHAR far* serverNameEnd = strend(serverName);
  162.  
  163.   if (_tcsncmp(serverName, serverNamePrefix, serverNamePrefixLen) == 0)
  164.     serverName += serverNamePrefixLen;               // skip "\\"
  165.  
  166.   const _TCHAR far* ds = find(serverName, serverNameEnd, dirSeparator);
  167.   return string(serverName, 0, (int)(ds - serverName));
  168. }
  169.  
  170. //
  171. //
  172. //
  173. static string formDevice(const _TCHAR far* deviceName, bool isUNC)
  174. {
  175.   if (!deviceName)
  176.     return deviceName;
  177.  
  178.   const _TCHAR far* deviceNameEnd = strend(deviceName);
  179.  
  180.  
  181.   if (isUNC)
  182.     deviceNameEnd = find(deviceName, deviceNameEnd, dirSeparator);
  183.   else
  184.     deviceNameEnd = find(deviceName, deviceNameEnd, ldevTerminator);
  185.  
  186.   return string(deviceName, 0, (int)(deviceNameEnd - deviceName));
  187. }
  188.  
  189. //
  190. // Return a well formed path from any kind of filename part. A lone name
  191. // is assumed to be just the path
  192. //
  193. static string formPath(const _TCHAR far* path)
  194. {
  195.   if (!path)
  196.     return path;
  197.  
  198.   const _TCHAR far* pathEnd = strend(path);
  199.  
  200.   // Find the start of the path, skipping logical device or server+share
  201.   //
  202.   const _TCHAR far* dvs = find(path, pathEnd, ldevTerminator);
  203.   if (dvs < pathEnd) {
  204.     path = dvs + 1;  // skip logical device
  205.   }
  206.  
  207.   return string(path, 0, (int)(pathEnd - path));
  208. }
  209.  
  210. //
  211. // Return a well formed file from any kind of filename part. A lone name
  212. // is assumed to be just the file
  213. //
  214. //   "dir.x\file.ext"  -> "file"
  215. //   "dir.x\"          -> ""
  216. //   "file"            -> "file"
  217. //
  218. static string formFile(const _TCHAR far* file)
  219. {
  220.   if (!file)
  221.     return file;
  222.  
  223.   const _TCHAR far* fileEnd = strend(file);
  224.  
  225.   const _TCHAR far* ds = findl(fileEnd-1, file-1, dirSeparator);
  226.   if (ds >= file)
  227.     file = ds + 1;
  228.  
  229.   const _TCHAR far* es = findl(fileEnd-1, file-1, extSeparator);
  230.   if (es >= file)
  231.     fileEnd = es;
  232.  
  233.   return string(file, 0, (int)(fileEnd - file));
  234. }
  235.  
  236. //
  237. // Return a well formed extension from any kind of filename part. A lone name
  238. // is assumed to be just the extension and a '.' is prepended
  239. //
  240. //   "dir.x\file.ext"  -> ".ext"
  241. //   "dir.x\"          -> "."
  242. //   "ext"             -> ".ext"
  243. //
  244. static string formExt(const _TCHAR far* ext)
  245. {
  246.   if (!ext)
  247.     return ext;  // or extSeparator?
  248.  
  249.   const _TCHAR far* extEnd = strend(ext);
  250.  
  251.   const _TCHAR far* ds = findl(extEnd-1, ext-1, dirSeparator);
  252.   if (ds >= ext)
  253.     ext = ds + 1;
  254.  
  255.   const _TCHAR far* es = findl(extEnd-1, ext-1, extSeparator);
  256.   if (es >= ext)
  257.     return es;
  258.  
  259.   return string(extSeparator) + ext;
  260. }
  261.  
  262. //----------------------------------------------------------------------------
  263.  
  264. //
  265. //
  266. //
  267. TFileName::TFileName()
  268. {
  269. }
  270.  
  271. //
  272. //
  273. //
  274. TFileName::TFileName(const TFileName& src)
  275. :
  276.   ServerStr(src.ServerStr),
  277.   DeviceStr(src.DeviceStr),
  278.   PathStr(src.PathStr),
  279.   FileStr(src.FileStr),
  280.   ExtStr(src.ExtStr),
  281.   Unc(src.Unc)
  282. {
  283. }
  284.  
  285. //
  286. // Construct a filename in the form:
  287. //
  288. //   filename := [[servername]devicename][path][file[ext]]
  289. //
  290. //  where:
  291. //
  292. //   servername := \\multiname\         //
  293. //   devicename := name(: | \ | :\)
  294. //   sharename := name
  295. //   logicaldevice := name
  296. //
  297. //   path := multiname\[...]
  298. //   file := multiname
  299. //   ext := [.[name]]
  300. //
  301. //   name := (filecharset)[...]
  302. //   multiname := (filecharset | .)[...]
  303. //
  304. TFileName::TFileName(const _TCHAR far* serverName, const _TCHAR far* deviceName,
  305.                      const _TCHAR far* path, const _TCHAR far* file,
  306.                      const _TCHAR far* ext)
  307. {
  308.   ServerStr = formServer(serverName);
  309.  
  310.   Unc = serverName != 0;
  311.  
  312.   DeviceStr = formDevice(deviceName, Unc);
  313.   PathStr += formPath(path);
  314.   FileStr += formFile(file);
  315.   ExtStr += formExt(ext);
  316. }
  317.  
  318. //
  319. //
  320. //
  321. void
  322. TFileName::Parse(const _TCHAR far* freeform)
  323. {
  324.   const _TCHAR far* nextp;
  325.   const _TCHAR far* freeformEnd = strend(freeform);
  326.  
  327.   // Parse from the left, the server name and device if UNC "\\", or the
  328.   // logical device name if one.
  329.   //
  330.   nextp = skipstr(freeform, freeformEnd, serverNamePrefix);
  331.   if (nextp > freeform) {
  332.     Unc = true;
  333.     freeform = nextp;               // skip "\\"
  334.     nextp = find(freeform, freeformEnd, dirSeparator);
  335.     ServerStr = string(freeform, 0, (int)(nextp-freeform));
  336.     freeform = nextp + 1;               // skip past "\"
  337.  
  338.     nextp = find(freeform, freeformEnd, dirSeparator);
  339.     DeviceStr = string(freeform, 0, (int)(nextp-freeform));
  340.     freeform = nextp + 1;               // skip past "\"
  341.   }
  342.   else {
  343.     Unc = false;
  344.     ServerStr = "";
  345.  
  346.     nextp = find(freeform, freeformEnd, ldevTerminator);
  347.     if (nextp != freeformEnd) {
  348.       DeviceStr = string(freeform, 0, (int)(nextp-freeform));
  349.       freeform = nextp + 1;               // skip past "\/:"
  350.     }
  351.     else
  352.       DeviceStr = "";
  353.   }
  354.  
  355.   // Parse the extension and filename from the right.
  356.   //
  357.   nextp = findl(freeformEnd-1, freeform-1, extSeparator);
  358.   const _TCHAR far* dirp = findl(freeformEnd-1, freeform-1, dirSeparator);
  359.  
  360.   if (nextp > dirp) {
  361.     ExtStr = string(nextp, 0, (int)(freeformEnd-nextp));
  362.     freeformEnd = nextp;
  363.   }
  364.   else
  365.     ExtStr = "";
  366.  
  367.   FileStr = string(dirp+1, 0, (int)(freeformEnd - (dirp+1)));
  368.   freeformEnd = dirp;
  369.  
  370.   // What is left is the path
  371.   //
  372.   if (freeformEnd > freeform)
  373.     PathStr = string(freeform, 0, (int)(freeformEnd-freeform));
  374.   else
  375.     PathStr = "";
  376. }
  377.  
  378. //
  379. // Construct a filename given the full path in any form
  380. //
  381. TFileName::TFileName(const _TCHAR far* freeform)
  382. {
  383.   Parse(freeform);
  384. }
  385.  
  386. //
  387. // Construct a filename given the full path in any form
  388. //
  389. TFileName::TFileName(const string& freeform)
  390. {
  391.   Parse(freeform.c_str());
  392. }
  393.  
  394. //
  395. // Construct a special filename
  396. //
  397. TFileName::TFileName(TFileName::TSpecialType type)
  398. {
  399.   switch (type) {
  400. #if defined(BI_PLAT_WIN32)
  401.     case TempFile:
  402.     case TempDir: {
  403.       int tmpLen = ::GetTempPath(0,0);
  404.       _TCHAR* tmpPath = new _TCHAR[tmpLen];
  405.       ::GetTempPath(tmpLen, tmpPath);
  406.       if (type == TempDir) {
  407.         Parse(tmpPath);
  408.       }
  409.       else {
  410.         _TCHAR tmpFile[WIN95_LONGFILENAME_MAX];
  411.         ::GetTempFileName(tmpPath, "TFN", 0, tmpFile);
  412.  
  413.         Parse(tmpFile);
  414.       }
  415.       delete[] tmpPath;
  416.     }
  417.     break;
  418.     case CurrentDir: {
  419.       _TCHAR tmp[WIN95_LONGFILENAME_MAX];
  420.       ::GetCurrentDirectory(sizeof tmp, tmp);
  421.  
  422.       Parse(tmp);
  423.     }
  424.     break;
  425. #elif defined(BI_PLAT_WIN16)
  426.     case TempFile:
  427.     case TempDir: {
  428.       _TCHAR tmpFile[WIN95_LONGFILENAME_MAX];
  429.       ::GetTempFileName(0, "TFN", 0, tmpFile);
  430.  
  431.       Parse(tmpFile);
  432.       if (type == TempDir) {
  433.         // Strip off filename part...
  434.         //
  435.         FileStr = "";
  436.         ExtStr = "";
  437.       }
  438.     }
  439.     break;
  440.     case CurrentDir: {
  441.       _TCHAR tmp[WIN95_LONGFILENAME_MAX];
  442.       _tgetcwd(tmp, sizeof tmp);
  443.  
  444.       Parse(tmp);
  445.     }
  446.     break;
  447. #endif
  448.     case HomeDir: {
  449.       _TCHAR tmp[WIN95_LONGFILENAME_MAX];
  450.       ::GetWindowsDirectory(tmp, sizeof tmp);
  451.  
  452.       Parse(tmp);
  453.     }
  454.     break;
  455.     case BootDir:
  456.     case MachineDir:
  457.     case SharedDir:
  458.     break;
  459.     case SysDir: {
  460.       _TCHAR tmp[WIN95_LONGFILENAME_MAX];
  461.       ::GetSystemDirectory(tmp, sizeof tmp);
  462.       Parse(tmp);
  463.     }
  464.     break;
  465. #if defined(BI_PLAT_WIN32)
  466.     case ComputerName: {
  467.       _TCHAR tmp[WIN95_LONGFILENAME_MAX];
  468.       uint32 size = sizeof tmp;
  469.       ::GetComputerName(tmp, &size);
  470.       Parse(tmp);
  471.     }
  472.     break;
  473. #endif
  474.   }
  475. }
  476.  
  477. //
  478. //
  479. //
  480. TFileName&
  481. TFileName::operator =(const TFileName& src)
  482. {
  483.   Unc = src.Unc;
  484.   ServerStr = src.ServerStr;
  485.   DeviceStr = src.DeviceStr;
  486.   PathStr = src.PathStr;
  487.   FileStr = src.FileStr;
  488.   ExtStr = src.ExtStr;
  489.   return *this;
  490. }
  491.  
  492. //
  493. //
  494. //
  495. static void
  496. ForceFullPath(string canonical)
  497. {
  498.   _TCHAR buffer[WIN95_LONGFILENAME_MAX];
  499.   ::GetFullPathName(canonical.c_str(), sizeof buffer, buffer, 0);
  500.   canonical = buffer;
  501. }
  502.  
  503. //
  504. // Reassemble the filename parts into a canonical form & expand any relative
  505. // dirs
  506. //
  507. string
  508. TFileName::Canonical(bool forceUNC) const
  509. {
  510.   string canonical;
  511.  
  512.   if (forceUNC)
  513.     canonical = string(serverNamePrefix) + DeviceStr
  514.         + dirSeparatorCh + PathStr + dirSeparatorCh + FileStr + ExtStr;
  515.   else
  516.     canonical = GetParts(Server|Device|Path|File|Ext);
  517.  
  518.   ForceFullPath(canonical);
  519.  
  520.   return canonical;
  521. }
  522.  
  523. //
  524. //
  525. //
  526. string
  527. TFileName::ShortName(bool forceUNC) const
  528. {
  529.   _TCHAR tmp[WIN95_LONGFILENAME_MAX];
  530.   ::GetShortPathName(Canonical(forceUNC).c_str(), tmp, sizeof tmp);
  531.  
  532.   return string(tmp);
  533. }
  534.  
  535. //
  536. // Human readable form of the filename appropriate for use in titles
  537. //
  538. string TFileName::Title() const
  539. {
  540.   string canonical = Canonical();
  541.   _TCHAR tmp[WIN95_LONGFILENAME_MAX];
  542.   ::GetFileTitle(canonical.c_str(), tmp, sizeof tmp);
  543.  
  544.   return string(tmp);
  545. }
  546.  
  547. //
  548. // Human readable form of the filename squeezed to fit in 'maxLen' chars
  549. //
  550. string TFileName::Squeezed(int maxLen) const
  551. {
  552.   // Try subsequently smaller sets of parts until it fits into maxLen chars
  553.   //
  554.   static uint parts[] = {
  555.     Server | Device | Path | File | Ext,  // Whole thing
  556.     Server | Device | File | Ext,         
  557.     File | Ext,
  558.     File,
  559.   };
  560.   for (int i = 0; i < sizeof parts / sizeof parts[0]; i++) {
  561.     string attempt = GetParts(parts[i]);
  562.     if (attempt.length() <= (uint)maxLen) {
  563.       return attempt;
  564.     }
  565.   }
  566.   return "";
  567. }
  568.  
  569. //
  570. //
  571. //
  572. bool
  573. TFileName::IsValid() const
  574. {
  575.   OFSTRUCT ofs;
  576.   ofs.cBytes = sizeof ofs;
  577.   return ::OpenFile(Canonical().c_str(), &ofs, OF_PARSE) != -1;
  578. }
  579.  
  580. //
  581. //
  582. //
  583. bool
  584. TFileName::Exists() const
  585. {
  586.   OFSTRUCT ofs;
  587.   ofs.cBytes = sizeof ofs;
  588.   return ::OpenFile(Canonical().c_str(), &ofs, OF_EXIST) != -1;
  589. }
  590.  
  591.  
  592. //
  593. // Reassemble any logical subset of filename parts
  594. //
  595. string
  596. TFileName::GetParts(uint p) const
  597. {
  598.   string part;
  599.  
  600.   if (Unc) {
  601.     if (p & Server) {
  602.       part += serverNamePrefix;
  603.       part += ServerStr;
  604.       if (p & Device)
  605.         part += dirSeparatorCh;
  606.     }
  607.     if ((p & Device) && DeviceStr.length() > 0) {
  608.       part += DeviceStr;
  609.       if ((p & Path) || (p & File))
  610.         part += dirSeparatorCh;
  611.     }
  612.   }
  613.   else {
  614.     if ((p & Device) && DeviceStr.length() > 0) {
  615.       part += DeviceStr;
  616.       part += ldevTerminator;
  617.     }
  618.   }
  619.  
  620.   if ((p & Path) && PathStr.length() > 0)
  621.     part += PathStr + dirSeparatorCh;
  622.  
  623.   if ((p & File) && FileStr.length() > 0)
  624.     part += FileStr;
  625.  
  626.   if ((p & Ext) && ExtStr.length() > 0)
  627.     part += ExtStr;
  628.  
  629.   return part;
  630. }
  631.  
  632. //
  633. //
  634. //
  635. bool
  636. TFileName::HasParts(uint p) const
  637. {
  638.   bool has = false;
  639.   if (p & Server)
  640.     has |= ServerStr.length() > 0;
  641.   if (p & Device)
  642.     has |= DeviceStr.length() > 0;
  643.   if (p & Path)
  644.     has |= PathStr.length() > 0;
  645.   if (p & File)
  646.     has |= FileStr.length() > 0;
  647.   if (p & Ext)
  648.     has |= ExtStr.length() > 0;
  649.   return has;
  650. }
  651.  
  652. //
  653. //
  654. //
  655. void
  656. TFileName::SetPart(uint p, const string& partStr)
  657. {
  658.   if (p & Server)
  659.     ServerStr = partStr;
  660.   if (p & Device)
  661.     DeviceStr = partStr;
  662.   if (p & Path)
  663.     PathStr = partStr;
  664.   if (p & File)
  665.     FileStr = partStr;
  666.   if (p & Ext)
  667.     ExtStr = partStr;
  668. }
  669.  
  670. //
  671. //
  672. //
  673. void
  674. TFileName::MergeParts(uint p, const TFileName& source)
  675. {
  676.   // Walk thru bits & SetPart(p) from source.GetParts(p)
  677.   //
  678.   if (p & Server)
  679.     ServerStr = source.GetParts(Server);
  680.   if (p & Device)
  681.     DeviceStr = source.GetParts(Device);
  682.   if (p & Path)
  683.     PathStr = source.GetParts(Path);
  684.   if (p & File)
  685.     FileStr = source.GetParts(File);
  686.   if (p & Ext)
  687.     ExtStr = source.GetParts(Ext);
  688. }
  689.  
  690. //
  691. //
  692. //
  693. void
  694. TFileName::StripParts(uint p)
  695. {
  696.   if (p & Server)
  697.     ServerStr = "";
  698.   if (p & Device)
  699.     DeviceStr = "";
  700.   if (p & Path)
  701.     PathStr = "";
  702.   if (p & File)
  703.     FileStr = "";
  704.   if (p & Ext)
  705.     ExtStr = "";
  706. }
  707.  
  708. //----------------------------------------------------------------------------
  709.  
  710. //
  711. //
  712. //
  713. void
  714. TFileName::Remove() const
  715. {
  716. #if defined(BI_PLAT_WIN32)
  717.   if (!::DeleteFile(Canonical().c_str()))
  718.     ::RemoveDirectory(Canonical().c_str());
  719. #else
  720.   if (_tremove(Canonical().c_str()) != 0)
  721.     _trmdir(Canonical().c_str());
  722. #endif
  723. }
  724.  
  725. //
  726. //
  727. //
  728. void
  729. #if defined(BI_PLAT_WIN32)
  730. TFileName::Move(const TFileName& newName, uint32 how)
  731. #else
  732. TFileName::Move(const TFileName& newName, uint32 /*how*/)
  733. #endif
  734. {
  735. #if defined(BI_PLAT_WIN32)
  736.   //
  737.   // Contrary to the help\MSDN MoveFileEx fails under Win95. (as of 2/97)
  738.   //
  739.   bool retval = false;
  740.   if( !TSystem::IsWin95() )
  741.     retval = ::MoveFileEx(Canonical().c_str(), newName.Canonical().c_str(), how);
  742.   else
  743.     retval = ::MoveFile(Canonical().c_str(), newName.Canonical().c_str());
  744.  
  745.   if(retval)
  746.    *this = newName;
  747. #else
  748.   _trename(Canonical().c_str(), newName.Canonical().c_str());
  749. #endif
  750. }
  751.  
  752. //
  753. //
  754. //
  755. void
  756. TFileName::Copy(const TFileName& newName, bool failIfExists) const
  757. {
  758. #if defined(BI_PLAT_WIN32)
  759.   ::CopyFile(Canonical().c_str(), newName.Canonical().c_str(), failIfExists);
  760. #else
  761.   FILE *in;
  762.   FILE *out;
  763.   _TCHAR c;
  764.  
  765.   if (failIfExists) {
  766.     out = _tfopen(newName.Canonical().c_str(), "r");
  767.     if (!out)
  768.       return;
  769.     fclose(out);
  770.   }
  771.  
  772.   out = _tfopen(newName.Canonical().c_str(), "w");
  773.   if (!out)
  774.     return;
  775.   in = _tfopen(Canonical().c_str(), "r");
  776.   if (!in) {
  777.     fclose(out);
  778.     return;
  779.   }
  780.  
  781.   while ((c = _gettc(in)) != 0) // != 0 part to get by compiler warning
  782.     _puttc(c, out);
  783.  
  784.   fclose(in);
  785.   fclose(out);
  786. #endif
  787. }
  788.  
  789. //
  790. //
  791. //
  792. int
  793. TFileName::CreateDir() const
  794. {
  795. #if defined(BI_PLAT_WIN32)
  796.   return ::CreateDirectory(Canonical().c_str(), 0);  //LPSECURITY_ATTRIBUTES
  797. /*
  798. BOOL CreateDirectoryEx(
  799.     LPCTSTR  lpTemplateDirectory, // pointer to path string of template directory
  800.     LPCTSTR  lpNewDirectory,  // pointer to path string of directory to create
  801.     LPSECURITY_ATTRIBUTES  lpSecurityAttributes // pointer to security descriptor
  802.    );
  803. */
  804. #else
  805.   return _tmkdir(Canonical().c_str()) == 0;
  806. #endif
  807. }
  808.  
  809. //
  810. //
  811. //
  812. int
  813. TFileName::ChangeDir() const
  814. {
  815. #if defined(BI_PLAT_WIN32)
  816.   return ::SetCurrentDirectory(Canonical().c_str());
  817. #else
  818.   return _tchdir(Canonical().c_str()) == 0;
  819. #endif
  820. }
  821.  
  822. //----------------------------------------------------------------------------
  823.  
  824. TFileNameIterator::TFileNameIterator(const string& wildName)
  825. :
  826. #if defined(BI_PLAT_WIN32)
  827.   Handle(::FindFirstFile(wildName.c_str(), &Data)),
  828. #endif
  829.   Done(false)
  830. {
  831. #if !defined(BI_PLAT_WIN32)
  832.   Done = _tfindfirst(wildName.c_str(), &Data, 0x3F) < 0;  // All attributes
  833. #endif
  834. }
  835.  
  836. TFileNameIterator::~TFileNameIterator()
  837. {
  838. #if defined(BI_PLAT_WIN32)
  839.   if (Handle != INVALID_HANDLE_VALUE)
  840.     ::FindClose(Handle);
  841. #endif
  842. }
  843.  
  844. #if defined(BI_PLAT_WIN32)
  845. const WIN32_FIND_DATA&
  846. TFileNameIterator::operator ++()
  847. {
  848.   if (!::FindNextFile(Handle, &Data))
  849.     Done = true;
  850.   return Data;
  851. }
  852. #else
  853.  
  854. const ffblk&
  855. TFileNameIterator::operator ++()
  856. {
  857.   if (::_tfindnext(&Data) < 0)
  858.     Done = true;
  859.   return Data;
  860. }
  861. #endif
  862.